#include <g-bios.h>
#include <arch/s3c24xx.h>
#include <core/gpu.h>


//
#define LCD_REFLESH_HZ 60
//

// fill the value exactly same as the datasheet, DO NOT minus 1!
#if 1
//
#define LCD_WIDTH   480
#define LCD_HEIGHT  272
// vertical
#define VBP       2
#define VFP       4
#define VSPW     10
// horizontal
#define HBP       4
#define HFP       8
#define HSPW     41
#else
//
#define LCD_WIDTH   240
#define LCD_HEIGHT  320
// vertical
#define VBP       4
#define VFP       4
#define VSPW      3
// horizontal
#define HBP      13
#define HFP      13
#define HSPW     31
#endif

//
#define PNRMODE   3
#define BPPMODE   BPP16_TFT
#define FRM565    1


////////////////////////////////
#define VCLK     (LCD_REFLESH_HZ * ((VSPW + VBP + LCD_HEIGHT + VFP) * (HSPW + HBP + LCD_WIDTH + HFP)))
#define CLKVAL   (HCLOCK / (VCLK * 2) - 1)

static void __INLINE__ S3cGpuWrite(unsigned long ulVal, unsigned long ulAddr)
{
	WriteLong(ulVal, S3C24XX_LCD_BASE + ulAddr);
}

#if 0
static __INLINE__  unsigned long S3cGpuRead(unsigned long ulAddr)
{
	return ReadLong(S3C24XX_LCD_BASE +  ulAddr);
}
#endif

static __INIT__ int S3c24xxGpuInit(void)
{
	ULONG ulVideoBuffer;
	UINT16 *pVideoBuffer;
	UINT32 uVal;

#if BPPMODE == BPP16_TFT
	#if FRM565 == 1
		#define PIX_FMT  PIX_RGB16
	#else
		#define PIX_FMT  PIX_RGB15
	#endif
#elif BPPMODE == BPP24_TFT
	#define PIX_FMT PIX_RGB24
#else
	#error
#endif

	// alloc and init the video buffer:
	pVideoBuffer = VideoMemAlloc(LCD_WIDTH, LCD_HEIGHT, PIX_FMT, &ulVideoBuffer);
	if (NULL == pVideoBuffer)
	{
		return -ENOMEM;
	}

	uVal = ReadLong(0x4c00000c);
	uVal |= 0x20;
	WriteLong(uVal, 0x4c00000c);

	S3cGpuWrite(ulVideoBuffer >> 1, LCDSADDR1);
	S3cGpuWrite(((ulVideoBuffer >> 1) & 0x1fffff) + LCD_WIDTH * LCD_HEIGHT, LCDSADDR2);
	S3cGpuWrite(LCD_WIDTH, LCDSADDR3);

	S3cGpuWrite(CLKVAL << 8 | PNRMODE << 5 | BPPMODE << 1 | 1, LCDCON1);
	S3cGpuWrite((VBP - 1) << 24 | (LCD_HEIGHT - 1) << 14 | (VFP - 1) << 6 | (VSPW - 1), LCDCON2);
	S3cGpuWrite((HBP - 1) << 19 | (LCD_WIDTH - 1) << 8 | (HFP - 1), LCDCON3);
	S3cGpuWrite(HSPW - 1, LCDCON4);
	S3cGpuWrite(FRM565 << 11 | 1 << 9 | 1 << 8 | 1 << 3 | 1, LCDCON5);

	S3cGpuWrite(0, TCONSEL);

	WriteLong(0xaaaaaaaa, S3C24XX_GPCCON);
	WriteLong(0xaaaaaaaa, S3C24XX_GPDCON);

	return 0;
}

DRIVER_INIT(S3c24xxGpuInit);

